<template>
  <div class="resize-box" :class="[direction, theme, { dragging: isDragging }]" ref="container">
    <div class="pane first-pane" :style="firstPaneStyle">
      <slot name="first"></slot>
    </div>

    <div
      class="resizer"
      :class="{ active: isDragging }"
      @mousedown="startDrag"
      @touchstart.prevent="startDrag"
    >
      <div class="resizer-handle">
        <slot name="resizer">
          <div class="default-handle"></div>
        </slot>
      </div>
    </div>

    <div class="pane second-pane" :style="secondPaneStyle">
      <slot name="second"></slot>
    </div>

    <!-- 拖拽时的视觉反馈线 -->
    <div v-show="isDragging" class="drag-indicator" :style="indicatorStyle"></div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'

const props = defineProps({
  direction: {
    type: String,
    default: 'horizontal',
    validator: (value) => ['horizontal', 'vertical'].includes(value)
  },
  initialSize: {
    type: [Number, String],
    default: '50%'
  },
  minSize: {
    type: Number,
    default: 100
  },
  maxSize: {
    type: Number,
    default: 0
  },
  theme: {
    type: String,
    default: 'light',
    validator: (value) => ['light', 'dark', 'blue', 'green', 'purple'].includes(value)
  },
  disabled: {
    type: Boolean,
    default: false
  },
  snapPoints: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['resize-start', 'resizing', 'resize-end'])

const container = ref(null)
const isDragging = ref(false)
const startPos = ref(0)
const startSize = ref(0)
const currentSize = ref(props.initialSize)
const containerRect = ref({ width: 0, height: 0 })

// 计算第一个面板的样式
const firstPaneStyle = computed(() => {
  if (typeof currentSize.value === 'number') {
    return { [props.direction === 'horizontal' ? 'width' : 'height']: `${currentSize.value}px` }
  } else {
    return { [props.direction === 'horizontal' ? 'width' : 'height']: currentSize.value }
  }
})

// 第二个面板自动填充剩余空间
const secondPaneStyle = computed(() => {
  return { flex: 1 }
})

// 指示线样式
const indicatorStyle = computed(() => {
  if (!isDragging.value) return {}

  const size =
    typeof currentSize.value === 'number'
      ? currentSize.value
      : (parseFloat(currentSize.value) / 100) *
        containerRect.value[props.direction === 'horizontal' ? 'width' : 'height']

  return props.direction === 'horizontal'
    ? { left: `${size}px`, width: '2px' }
    : { top: `${size}px`, height: '2px' }
})

// 初始化容器尺寸
const initContainerSize = () => {
  if (!container.value) return
  containerRect.value = {
    width: container.value.clientWidth,
    height: container.value.clientHeight
  }
}

// 开始拖拽
const startDrag = (e) => {
  if (props.disabled) return

  initContainerSize()
  isDragging.value = true
  startPos.value =
    props.direction === 'horizontal'
      ? e.clientX || e.touches[0].clientX
      : e.clientY || e.touches[0].clientY

  // 获取当前尺寸
  if (typeof props.initialSize === 'string' && props.initialSize.includes('%')) {
    const parentSize =
      props.direction === 'horizontal' ? containerRect.value.width : containerRect.value.height
    startSize.value = (parseFloat(props.initialSize) / 100) * parentSize
  } else if (typeof currentSize.value === 'number') {
    startSize.value = currentSize.value
  } else {
    startSize.value = parseFloat(currentSize.value)
  }

  document.addEventListener('mousemove', handleDrag)
  document.addEventListener('touchmove', handleDrag, { passive: false })
  document.addEventListener('mouseup', stopDrag)
  document.addEventListener('touchend', stopDrag)

  document.body.style.cursor = props.direction === 'horizontal' ? 'col-resize' : 'row-resize'
  document.body.style.userSelect = 'none'

  emit('resize-start', { size: startSize.value, direction: props.direction })
}

// 处理拖拽
const handleDrag = (e) => {
  if (!isDragging.value) return
  e.preventDefault()

  const currentPos =
    props.direction === 'horizontal'
      ? e.clientX || e.touches[0].clientX
      : e.clientY || e.touches[0].clientY

  const delta = currentPos - startPos.value
  let newSize = startSize.value + delta

  // 应用最小尺寸限制
  newSize = Math.max(props.minSize, newSize)

  // 限制最大尺寸
  const parentSize =
    props.direction === 'horizontal' ? containerRect.value.width : containerRect.value.height

  const maxSize = props.maxSize > 0 ? props.maxSize : parentSize * 0.95
  newSize = Math.min(maxSize, newSize)

  // 应用吸附点
  if (props.snapPoints.length > 0) {
    const snapThreshold = 10 // 吸附阈值
    for (const point of props.snapPoints) {
      if (Math.abs(newSize - point) < snapThreshold) {
        newSize = point
        break
      }
    }
  }

  currentSize.value = newSize
  emit('resizing', { size: newSize, direction: props.direction })
}

// 停止拖拽
const stopDrag = () => {
  if (!isDragging.value) return

  isDragging.value = false

  document.removeEventListener('mousemove', handleDrag)
  document.removeEventListener('touchmove', handleDrag)
  document.removeEventListener('mouseup', stopDrag)
  document.removeEventListener('touchend', stopDrag)

  document.body.style.cursor = ''
  document.body.style.userSelect = ''

  emit('resize-end', { size: currentSize.value, direction: props.direction })
}

// 响应窗口大小变化
const handleResize = () => {
  initContainerSize()
}

// 组件挂载时添加事件监听
onMounted(() => {
  initContainerSize()
  window.addEventListener('resize', handleResize)
})

// 组件卸载时移除事件监听
onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  document.removeEventListener('mousemove', handleDrag)
  document.removeEventListener('touchmove', handleDrag)
  document.removeEventListener('mouseup', stopDrag)
  document.removeEventListener('touchend', stopDrag)
})
</script>

<style scoped>
.resize-box {
  display: flex;
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.resize-box.horizontal {
  flex-direction: row;
}

.resize-box.vertical {
  flex-direction: column;
}

.pane {
  overflow: auto;
  position: relative;
  transition: background-color 0.2s;
}

.first-pane {
  flex-shrink: 0;
}

.second-pane {
  flex: 1;
  min-width: 0;
  min-height: 0;
}

.resizer {
  position: relative;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  user-select: none;
  touch-action: none;
  transition: background-color 0.2s;
}

.resize-box.horizontal > .resizer {
  width: 16px;
  cursor: col-resize;
}

.resize-box.vertical > .resizer {
  height: 16px;
  cursor: row-resize;
}

.resizer-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.default-handle {
  background-color: #e8eaef;
  border-radius: 4px;
  transition: all 0.2s ease;
  position: relative;
  z-index: 2;
}

.resize-box.horizontal > .resizer > .resizer-handle > .default-handle {
  width: 4px;
  height: 40px;
}

.resize-box.vertical > .resizer > .resizer-handle > .default-handle {
  width: 40px;
  height: 4px;
}

/* 拖拽状态样式 */
.resizer.active,
.resizer:hover {
  background-color: rgba(22, 93, 255, 0.06);
}

.resizer.active .default-handle,
.resizer:hover .default-handle {
  background-color: #165dff;
}

/* 拖拽指示线 */
.drag-indicator {
  position: absolute;
  z-index: 100;
  background-color: #165dff;
  pointer-events: none;
  box-shadow: 0 0 4px rgba(22, 93, 255, 0.6);
}

.resize-box.horizontal .drag-indicator {
  top: 0;
  bottom: 0;
  width: 2px;
}

.resize-box.vertical .drag-indicator {
  left: 0;
  right: 0;
  height: 2px;
}

/* 主题样式 */
.light .default-handle {
  background-color: #e8eaef;
}

.dark {
  background-color: #1d1d1d;
}

.dark .pane {
  background-color: #2a2a2a;
  color: #e0e0e0;
}

.dark .default-handle {
  background-color: #555;
}

.dark .resizer.active,
.dark .resizer:hover {
  background-color: rgba(22, 93, 255, 0.1);
}

.blue .default-handle {
  background-color: #91d5ff;
}

.blue .resizer.active,
.blue .resizer:hover {
  background-color: rgba(22, 93, 255, 0.1);
}

.green .default-handle {
  background-color: #b7eb8f;
}

.green .resizer.active,
.green .resizer:hover {
  background-color: rgba(82, 196, 26, 0.1);
}

.purple .default-handle {
  background-color: #d3adf7;
}

.purple .resizer.active,
.purple .resizer:hover {
  background-color: rgba(114, 46, 209, 0.1);
}

/* 优化拖拽性能 */
.resize-box.dragging .pane {
  transition: none;
  pointer-events: none;
}

.resize-box.dragging .resizer {
  background-color: rgba(22, 93, 255, 0.1);
}
</style>
